/**************************************************************************************************
 * @file        os_thread.h
 * @brief
 *跨平台线程API封装，支持Windows、Linux、macOS等系统的线程创建、管理和同步
 * @details
 *提供统一的线程接口，包括线程创建、运行、挂起、线程名设置、销毁、优先级设置等功能，
 *              屏蔽不同操作系统的底层差异，使得项目可专注于业务的实现，简化多线程编程复杂度。
 *
 * @author      taoist.luo
 * @version     1.0.0
 * @date        2024-09
 *
 * Copyright (c) 2024 taoist.luo (https://gitee.com/harmonyluo(https://blog.csdn.net/harmonyluo))
 *
 * MIT License
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 *all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 *************************************************************************************************/
#pragma once

#include <atomic>
#include <chrono>
#include <condition_variable>
#include <cstdint>
#include <functional>
#include <memory>
#include <mutex>
#include <string>
#include <thread>
#include <utility>

#include "containers/os_vector.h"

#ifdef _WIN32
#include <windows.h>
#else
#include <pthread.h>
#include <string.h>
#include <sys/prctl.h>
#include <unistd.h>
#endif

// 看门狗功能开关
#define ENABLE_THREAD_WATCHDOG 1
class os_thread {
 public:
  // 线程优先级枚举
  enum priority_e {
    PRIORITY_LOWEST = 0,
    PRIORITY_LOW,
    PRIORITY_NORMAL,
    PRIORITY_HIGH,
    PRIORITY_HIGHEST
  };

  // 线程状态枚举
  enum state_e {
    STATE_UNINITIALIZED,  // 未初始化 new 之后
    STATE_INITIALIZED,    // 已初始化 create 之后
    STATE_PRE_RUNNING,  // 调用了start，线程已经启动,但未运行用户线程函数
    STATE_RUNNING,         // 运行中  start 并且运行之后
    STATE_PAUSED,          // 暂停(悬挂) 调用pause 之后
    STATE_PRE_TERMINATED,  // 终止中
    STATE_TERMINATED,      // 已终止 终止之后
    STATE_DETACHED,        // 已分离
  };

  // 函数类型枚举
  enum function_type_e {
    FUNCTION_SHORT_TASK,  // 短时间任务，周期性调用
    FUNCTION_LONG_TASK    // 长时间运行任务，包含自己的主循环
  };
  enum check_state_e {
    STATE_CHECK_OK,
    STATE_CHECK_TERMINATED,
  };

  // 构造函数和析构函数
  os_thread();
  ~os_thread();

  // 禁止拷贝构造和赋值
  os_thread(const os_thread&) = delete;
  os_thread& operator=(const os_thread&) = delete;

  /*******************************************************************************
   * @brief 线程创建
   *
   * @param func: 用户线程执行的函数
   * @param type: FUNCTION_SHORT_TASK,
   短时间任务，周期性被调用，周期由interval指定
   *              FUNCTION_LONG_TASK 长时间运行任务，包含自己的主循环
   * @param
   interval:单位ms,仅对短时任务有效,短时任务如果设置了该间隔，则没执行一次短时任务之后，
                      休眠间隔该ms之后，再次执行用户函数
                      若为0，则执行完之后，线程退出}
   * @param args: 可变惨的用户参数
   * @return true :成功,false:失败
   * @note 无
   * *****************************************************************************/
  template <typename Func, typename... Args>
  bool create(Func&& func, function_type_e type, int interval, Args&&... args);
  // 设置线程优先级,必须先调用create函数，才能调用 start
  bool set_priority(priority_e priority);

  // 启动线程
  bool start();
  // 阻塞等待线程启动,true： 正在运行，false:
  // 已经结束运行,启动之后未必就是运行态，也可能是挂起的
  bool wait_for_started();

  // 分离线程
  bool detach();

  // 等待线程结束
  bool join();

  // 设置线程属性（暂留接口）
  bool set_attributes();

  // 暂停（挂起）线程，必须先调用create函数，才能调用 pause
  void pause();

  // 恢复线程
  void resume();

  // 终止线程
  void terminate();
  // 获取线程状态
  state_e getState() const;

  // 检查线程是否正在运行
  bool is_running() const;

  // 检查线程是否已结束
  bool is_finished() const;

  // 获取原生线程句柄
  std::thread::id get_threadid() const;

  // 用户线程函数调用此函数进行喂狗和检查状态，STATE_CHECK_OK:则继续执行,STATE_CHECK_TERMINATED:
  // 则跳出循环
  check_state_e check_and_heart();
  // 线程名操作，必须在启动线程之前设置
  void set_thread_name(const std::string& name);
  const std::string& get_thread_name() const;
  // 线程休眠相关
  static void sleep_ms(uint32_t ms);
  static void sleep_us(uint32_t us);
  static void sleep_second(uint32_t second);
#if ENABLE_THREAD_WATCHDOG
  static void start_watchdog();
  static void stop_watchdog();
  static void register_watchdog_timeout_fun(std::function<void(os_thread*)> callback);
  static void set_watchdog_timeout(std::chrono::milliseconds timeout);
  static void register_thread(os_thread* thread);
  friend class WatchdogManager;
#endif

 private:
  void thread_proc(std::function<void()> func);
  bool set_priority_pri(priority_e priority);

 private:
  // 内部状态管理
  mutable std::mutex m_thread_mutex;
  std::atomic<state_e> m_state;
  // 用于判断底层线程是否真的运行
  std::atomic<bool> m_run_or_exit;
  std::condition_variable m_cond_running;
  mutable std::mutex m_mutex_running;

  // 线程对象
  std::unique_ptr<std::thread> m_thread;

  // 用于暂停/恢复的条件变量
  std::mutex m_pause_mutex;
  std::condition_variable m_pause_condition;
  std::atomic<bool> m_paused;
  std::function<void()> m_user_function;

  // 线程名称
  std::string m_thread_name;
  // 看门狗相关
  std::atomic<bool> m_need_heartbeat;  // 是否需要喂狗
  std::chrono::steady_clock::time_point m_last_heartbeat_time;  // 上次心跳时间
  mutable std::mutex m_heartbeat_mutex;  // 保护心跳时间的互斥锁
  std::chrono::milliseconds m_heartbeat_timeout;  // 心跳超时时间
  function_type_e m_function_type;
  int m_interval_time;
  priority_e m_priority;
};

/*******************************************************************************
 * @brief 线程自动检查心跳
 *
 * @param x: 线程对象指针
 * @return void
 * @note 无
 * *****************************************************************************/
#define AUTO_CHECK_THREAD_HEARTBEAT(x)                             \
  if (x->check_and_heart() == os_thread::STATE_CHECK_TERMINATED) { \
    return;                                                        \
  }

template <typename Func, typename... Args>
bool os_thread::create(Func&& func, function_type_e type, int interval,Args&&... args) 
{
  std::lock_guard<std::mutex> lock(m_thread_mutex);
  if (m_state != STATE_UNINITIALIZED) {
    return false;
  }
  m_user_function = std::bind(std::forward<Func>(func), std::forward<Args>(args)...);
  m_function_type = type;  // 保存函数类型
  m_state = STATE_INITIALIZED;
  m_interval_time = interval;

#if ENABLE_THREAD_WATCHDOG
  os_thread::register_thread(this);
#endif
  return true;
}